#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "ui_connect.h"
//#include "ui_server.h"
#include "serverwin.h"
#include "connectwin.h"


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <Board.h>
#include <item.h>

using namespace std;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    /*prepare scence and item object*/
    scene = new QGraphicsScene();
    scene->setSceneRect(0, 0, 400, 400);
    i = new Item();
    i->setPos(0, 0);

    dconnect = new QDialog;
    dserver = new QDialog;
    QString message = tr("Witamy w grze Snake!");
    statusBar()->showMessage(message);

    //set status info for each action
    ui->actionStartGame->setStatusTip(tr("Rozpocznij nową gre"));
    ui->actionConnect->setStatusTip(tr("Dołącz do gry"));
    ui->actionServer->setStatusTip(tr("Utwórz własną gre"));
    ui->actionBest->setStatusTip(tr("Najlepsze wyniki"));
    ui->actionAbout->setStatusTip("Techniczne informacje o programie");
    ui->actionRules->setStatusTip("Zasady gry");
    ui->actionExit->setStatusTip("Zakończ działanie programu");


}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::paintBoard(short board[50][50]){
    i->set(board);
    scene->addItem(i);
    ui->graphicsView->setScene(scene);
    ui->graphicsView->show();
}

void MainWindow::on_actionStartGame_triggered()
{    
/* utworzenie węża */
    Snake ss = Snake();
    Position ps = Position();
    ps.Set(30, 30);
    ss.AddElement(ps);
    ps.Set(31, 30);
    ss.AddElement(ps);
    ps.Set(32, 30);
    ss.AddElement(ps);
    ps.Set(33, 30);
    ss.AddElement(ps);
    ps.Set(34, 30);
    ss.AddElement(ps);
    ps.Set(35, 30);
    ss.AddElement(ps);
    ps.Set(36, 30);
    ss.AddElement(ps);
//



 Board br = Board(); // tworzenie tablicy na serwerze
 br.ClearBoard(); // czyszczenie tablicy
 br.SetBorders(); // ustawianie scian na planszy

 br.SetFirst(ss); // polozenie pierwszego weza na planszy
 paintBoard(br.plansza);

 //-----------------------------------------------------------
 // rozpoczecie gry - NIESKONCZONA PETLA NA WATKU

int kierunek = 1; // zmienna odpowiadajaca za kierunek
 Snake tmp1 = ss; // pomocniczy waz
 tmp1.MoveStep(kierunek); // ruch na pomocniczym wezu - symulacja
 int decyzja = br.CheckFirst(tmp1); // sprawdzanie ruchu
 if(decyzja == -1){ // jablko
     ss.MoveStep(kierunek); // przesuniecie faktycznego weza bez kasowania ogona zeby urósl po zjedzeniu jablka
     br.SetFirst(ss); // wpisanie nowego weza do tablicy
 }
 else if(decyzja == 8){ // sciana
// komunikat o przegranej
 }
 else if(decyzja == 2){ // drugi gracz
// komunikat o przegranej
 }
 else if(decyzja == 0){ // zwykly ruch na puste pole
ss.MoveStep(kierunek); // przesuniecie faktycznego weza
ss.RemoveTail(); // usuniecie ostatniego pola ogona po przesunieciu
br.SetFirst(ss); // wpisanie nowego weza do tablicy
 }

paintBoard(br.plansza);
//--------------------------------------------
// koniec petli gry



}
int MainWindow::on_actionConnect_triggered()
{
    ConnectWin cw;
    this->setDisabled(1);
    cw.show();
    if(cw.exec())//if sw is accepted(Ok was clicked)
    {
        int sockfd, portno, n;
        struct sockaddr_in serv_addr;
        struct hostent *server;

        char buffer[256];

        portno = cw.getPort().toInt();
        sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (sockfd < 0)
        {
            QMessageBox::about(this, tr("Błąd"),
                tr("Wystąpił błąd podczas otwierania socketu"));
            return -1;
        }

        long addr=inet_addr(cw.getIP().toStdString().c_str());
        server=gethostbyaddr((char*)&addr,sizeof(addr),AF_INET);


        if (server == NULL) {
            QMessageBox::about(this, tr("Błąd"),
                tr("Wystąpił błąd podczas ..."));
            return -1;
        }
        bzero((char *) &serv_addr, sizeof(serv_addr));
        serv_addr.sin_family = AF_INET;
        bcopy((char *)server->h_addr,
             (char *)&serv_addr.sin_addr.s_addr,
             server->h_length);
        serv_addr.sin_port = htons(portno);
        if (::connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0){
            QMessageBox::about(this, tr("Błąd"),
                tr("Wystąpił błąd podczas ..."));
            return -1;
        }
        printf("Podaj wiadomosc: ");
        bzero(buffer,256);

        QString s = "GIT";

        strcpy(buffer, s.toStdString().c_str());
        n = write(sockfd,buffer,strlen(buffer));
        if (n < 0){
            QMessageBox::about(this, tr("Błąd"),
                tr("Wystąpił błąd podczas ..."));
            return -1;
        }
        bzero(buffer,256);
        n = read(sockfd,buffer,255);
        if (n < 0){
            QMessageBox::about(this, tr("Błąd"),
                tr("Wystąpił błąd podczas ..."));
            return -1;
        }
        std::string ss(buffer);
        s.fromStdString(ss);
        QMessageBox::about(this, tr("Msg"),
            "Wiadomość:" + s);


        ::close(sockfd);
    }
    else
    {
    }
    this->setEnabled(1);
}
int MainWindow::on_actionServer_triggered()
{
    ServerWin sw;
    this->setDisabled(1);
    sw.show();
    if(sw.exec())//if sw is accepted(Ok was clicked)
    {
        /**************kod prezesa*****************/
        int sockfd, newsockfd, portno;
        socklen_t clilen;
        char buffer[256];
        struct sockaddr_in serv_addr, cli_addr;
        int n;

        sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (sockfd < 0){
            QMessageBox::about(this, tr("Błąd"),
                 tr("Wystąpił błąd podczas otwierania socketu"));
            return -1;
        }
        bzero((char *) &serv_addr, sizeof(serv_addr));
        portno = sw.getPort().toInt();//getting port from form
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_addr.s_addr = INADDR_ANY;
        serv_addr.sin_port = htons(portno);
        if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0){
            QMessageBox::about(this, tr("Błąd"),
                 tr("Wystąpił błąd podczas tworzenia socketu"));
            return -1;
        }
        listen(sockfd,5);
        clilen = sizeof(cli_addr);
        newsockfd = accept(sockfd,
                    (struct sockaddr *) &cli_addr,
                    &clilen);
        if (newsockfd < 0)
        {
            QMessageBox::about(this, tr("Błąd"),
                tr("Wystąpił błąd podczas ustanawiania połączenia"));
            return -1;
        }
        bzero(buffer,256);
        n = read(newsockfd,buffer,255);
        if (n < 0)
        {
            QMessageBox::about(this, tr("Błąd"),
                tr("Wystąpił błąd podczas czytania danych"));
            return -1;
        }
        QMessageBox::about(this, tr("Wiadomość"),
            tr("Przesłana wiadomość: "+n));

        n = write(newsockfd,"Wiadomosc zostala przeslana poprawnie.",18);
        if (n < 0)
        {
            QMessageBox::about(this, tr("Błąd"),
                tr("Wystąpił błąd podczas wysyłania danych"));
            return -1;
        }
        ::close(newsockfd);
        ::close(sockfd);
    }
    else
    {
    }
    this->setEnabled(1);
}
void MainWindow::on_actionBest_triggered()
{
    QMessageBox::about(this, tr("Najlepsze wyniki"),
             tr("Lista największych wymiataczy w Snake'a"));
}
void MainWindow::on_actionExit_triggered()
{
    close();
}
void MainWindow::on_actionRules_triggered()
{
    QMessageBox::about(this, tr("Zasady gry"),
             tr("Zasady gry w Snake'a dla niekumatych"));
}
void MainWindow::on_actionAbout_triggered()
{
    QMessageBox::about(this, tr("O programie"),
             tr("Jakieś tam informacje techniczne o grze"));
}

void MainWindow::keyPressEvent(QKeyEvent *event){
// nacisniecie klawisza
}




